package src.Players;

import src.Util.*;
import src.Main;
import src.Packets.Equipment;

public class PlayerUpdateBlock
{
    private int[] otherEmotes = {0x337, 0x334, 0x335, 0x336};
    private int HAT = 0, CAPE = 1, AMULET = 2, WEAPON = 3, CHEST = 4, SHIELD = 5, LEGS = 7, HANDS = 9, FEET = 10, 
    RING = 12, ARROWS = 13;

    public PlayerUpdateBlock()
    {
    }

    public void writeMask(Stream str, int updateMask)
    {
        if(str == null)
        {
            return;
        }
        if(updateMask >= 0x100)
        {
            updateMask |= 0x40;
            str.writeByte(updateMask & 0xFF);
            str.writeByte(updateMask >> 8);
        }
        else
        {
            str.writeByte(updateMask);
        }
    }

    public void appendPlayerChatText(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        str.writeWordBigEndian(((p.chatTextColor & 0xFF) << 8) + (p.chatTextEffects & 0xFF));
        str.writeByte(p.rights);
        str.writeByteC(p.chatTextSize);
        str.writeBytes_reverse(p.chatText, p.chatTextSize, 0);
    }

    public void appendPlayerAppearance(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        Equipment e = new Equipment();
        Stream playerProps = new Stream(new byte[100]);
        playerProps.writeByte(0); //Playerlook
        playerProps.writeByte(0); //Headicon
        if(p.npcType == -1)
        {
            for(int i = 0; i < 4; i++)
            {
                if(p.equipment[i] > 0)
                {
                    playerProps.writeWord(0x200 + p.equipment[i]);
                }
                else
                {
                    playerProps.writeByte(0);
                }
            }
            if(p.equipment[CHEST] > 0)
            {
                    playerProps.writeWord(0x200 + p.equipment[CHEST]);
            }
            else
            {
                playerProps.writeWord(0x100 + 18); //Torso
            }
            if(p.equipment[SHIELD] > 0)
            {
                playerProps.writeWord(0x200 + p.equipment[SHIELD]);
            }
            else
            {
                playerProps.writeByte(0);
            }
            if(!e.isFullbody(p.equipment[CHEST]))
            {
                playerProps.writeWord(0x100 + 26); //pArms
            }
            else
            {
                playerProps.writeByte(0);
            }
            if(p.equipment[LEGS] > 0)
            {
                playerProps.writeWord(0x200 + p.equipment[LEGS]);
            }
            else
            {
                playerProps.writeWord(0x100 + 38); //pLegs
            }
            if(!e.isFullhat(p.equipment[HAT]) && !e.isFullmask(p.equipment[HAT]))
            {
                playerProps.writeWord(0x100 + 3); //pHead
            }
            else
            {
                playerProps.writeByte(0);
            }
            if(p.equipment[HANDS] > 0)
            {
                playerProps.writeWord(0x200 + p.equipment[HANDS]);
            }
            else
            {
                playerProps.writeWord(0x100 + 34); //pHands
            }
            if(p.equipment[FEET] > 0)
            {
                playerProps.writeWord(0x200 + p.equipment[FEET]);
            }
            else
            {
                playerProps.writeWord(0x100 + 43); //pFeet
            }
            if(!e.isFullmask(p.equipment[HAT]))
            {
                playerProps.writeWord(0x100 + 10); //pBeard
            }
            else
            {
                playerProps.writeByte(0);
            }
        }
        else
        {
            playerProps.writeWord(-1);
            playerProps.writeWord(p.npcType);
        }
        playerProps.writeByte(0); //Playerlook
        playerProps.writeByte(5); //Playerlook
        playerProps.writeByte(2); //Playerlook
        playerProps.writeByte(2); //Playerlook
        playerProps.writeByte(0); //Playerlook
        playerProps.writeWord(p.standEmote);
        playerProps.writeWord(otherEmotes[0]);
        playerProps.writeWord(p.walkEmote);
        playerProps.writeWord(otherEmotes[1]);
        playerProps.writeWord(otherEmotes[2]);
        playerProps.writeWord(otherEmotes[3]);
        playerProps.writeWord(p.runEmote);
        playerProps.writeQWord(usernameToLong(p.username));
        calculateCombat(p);
        playerProps.writeByte(p.combatLevel);
        playerProps.writeWord(0);
        str.writeByteC(playerProps.getOffset());
        str.writeBytes(playerProps.getBuffer(), playerProps.getOffset(), 0);
        playerProps.destruct();
        playerProps = null;
        e = null;
    }

    private void calculateCombat(Player p)
    {
        if(p == null)
        {
            return;
        }
        int attack = p.getLevelForXP(0);
        int defence = p.getLevelForXP(1);
        int strength = p.getLevelForXP(2);
        int hp = p.getLevelForXP(3);
        int prayer = p.getLevelForXP(5);
        int ranged = p.getLevelForXP(4);
        int magic = p.getLevelForXP(6);
        p.combatLevel = (int)((defence + hp + Math.floor(prayer / 2)) * 0.25) + 1; 
        double melee = (attack + strength) * 0.325; 
        double ranger = Math.floor(ranged * 1.5) * 0.325; 
        double mage = Math.floor(magic * 1.5) * 0.325; 
        if(melee >= ranger && melee >= mage)
        {
            p.combatLevel += melee;
        }
        else if(ranger >= melee && ranger >= mage)
        {
            p.combatLevel += ranger;
        }
        else if(mage >= melee && mage >= ranger)
        {
            p.combatLevel += mage;
        }
    }

    public void appendAnimationRequest(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        str.writeWordBigEndian(p.animRequest);
        str.writeByteC(p.animDelay);
    }

    public void appendGraphicsRequest(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        str.writeWordBigEndian(p.gfxRequest);
        str.writeDWord(p.gfxDelay);
    }

    public void appendFaceTo(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        str.writeWordBigEndian(p.faceToRequest);
    }

    public void appendHit1(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        str.writeByte(p.hitDiff1);
        if(p.posionHit1 == 0)
        {
            if(p.hitDiff1 > 0)
            {
                str.writeByteA(1);
            }
            else
            {
                str.writeByteA(0);
            }
        }
        else
        {
            str.writeByteA(2);
        }
        str.writeByteC(p.skillLvl[3]);
        str.writeByte(p.getLevelForXP(3));
    }

    public void appendMask400(Player p, Stream str)
    {
        if(p == null || str == null)
        {
            return;
        }
        str.writeByteS(p.absX);
        str.writeByteS(p.absY);
        str.writeByteS(1);
        str.writeByteS(1);
        str.writeWordBigEndianA(1);
        str.writeWordA(1);
        str.writeByteS(0);
    }

    private long usernameToLong(String s)
    {
        long l = 0L;
        for(int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);
            l *= 37L;
            if(c >= 'A' && c <= 'Z')
                l += (1 + c) - 65;
            else if(c >= 'a' && c <= 'z')
                l += (1 + c) - 97;
            else if(c >= '0' && c <= '9')
                l += (27 + c) - 48;
        }
        while(l % 37L == 0L && l != 0L) l /= 37L;
        return l;
    }
}